home *** CD-ROM | disk | FTP | other *** search
- /* PDlog Expand.c Derived from TN #95.
-
- Dave Hersey, Apple Developer Technical Support.
-
- 10/9/91… v1.0
- 2/25/92… v1.0.1 --> fixed lack of print handle tossing and added something to print. <dmh>
- 9/29/93… v1.0.2 --> fixed bug in Append_DITL (also in TN #95) which appends 2 extra bytes. <dmh>
- 6/20/95… v1.0.3 --> updated for Universal Headers and MWC-PPC <njvt>
-
- NOTE: Apple reserves the top half of the screen (where the current DITL
- items are located). Applications may use the bottom half of the screen to
- add items, but should not change any items in the top half of the screen.
- An application should expand the print dialogs only as much as is
- absolutely necessary.
-
- A global search and replace of 'Job' with 'Stl' will produce code that
- modifies the style dialog.
-
-
- */
-
- #include <Printing.h>
- #include <MixedMode.h>
-
- static TPPrDlg PrtJobDialog; /* pointer to job dialog */
-
- /*
-
- This points to the following structure:
-
- struct TPrDlg {
- DialogRecord Dlg; // The Dialog window
- ModalFilterUPP pFltrProc; // The Filter Proc.
- PItemUPP pItemProc; // The Item evaluating proc.
- THPrint hPrintUsr; // The user's print record.
- Boolean fDoIt;
- Boolean fDone;
- long lUser1; // Four longs for apps to hang global data.
- long lUser2; // Plus more stuff needed by the particular
- long lUser3; // printing dialog.
- long lUser4;
- };
- typedef struct TPrDlg TPrDlg;
- typedef TPrDlg *TPPrDlg;
- typedef TPPrDlg TPPrDlgRef;
-
- */
-
- /* Declare ‘pascal’ functions and procedures */
-
- extern short Append_DITL(TPPrDlg, short); /* Our AppendDITL function. */
- extern pascal TPPrDlg MyJobDlgInit(THPrint); /* Our extention to PrJobInit. */
- extern pascal void MyJobItems(TPPrDlg, short); /* Our modal item handler. */
- extern OSErr Print(void);
-
- #define MyDITL 256 /* resource ID of my DITL to be spliced onto job dialog */
-
- THPrint hPrintRec; /* handle to print record */
- long prFirstItem; /* save our first item here */
- long prPItemProc; /* we need to store the old itemProc here */
-
- /*-----------------------------------------------------------------------*/
- WindowPtr MyWindow;
- OSErr err;
- Str255 myStr;
-
- #if PRAGMA_ALIGN_SUPPORTED
- #pragma options align=mac68k
- #endif
-
- typedef
- struct dialog_item_struct
- {
- Handle handle; /* handle or procedure pointer for this item */
- Rect bounds; /* display rectangle for this item */
- char type; /* item type - 1 */
- char data[1]; /* length byte of data */
- }
- DialogItem, *DialogItemPtr, **DialogItemHandle;
-
- typedef
- struct append_item_list_struct
- {
- short max_index; /* number of items - 1 */
- DialogItem items[1]; /* first item in the array */
- }
- ItemList, *ItemListPtr, **ItemListHandle;
-
- typedef
- union signed_byte_union
- {
- short integer;
- char bytes[2];
- }
- ByteAccess;
-
-
- /* This routine appends all of the items of a specified DITL */
- /* onto the end of a specified DLOG — We don’t even need to know the format */
- /* of the DLOG */
-
- /* this will be done in 3 steps: */
- /* 1. append the items of the specified DITL onto the existing DLOG */
- /* 2. expand the original dialog window as required */
- /* 3. return the adjusted number of the first new user item */
-
-
- short Append_DITL(TPPrDlg dialog, short item_list_ID)
- {
- Point offset;
- Rect max_rect;
- ItemListHandle append_item_list; /* handle to DITL being appended */
- DialogItemPtr item; /* pointer to item being appended */
- ItemListHandle dlg_item_list; /* handle to DLOG's item list */
- short first_item;
- short new_items, data_size, i;
- ByteAccess usb;
- OSErr err;
-
- /*
- Using the original DLOG
-
- 1. Remember the original window Size.
- 2. Set the offset Point to be the bottom of the original window.
- 3. Subtract 5 pixels from bottom and right, to be added
- back later after we have possibly expanded window.
- 4. Get working Handle to original item list.
- 5. Calculate our first item number to be returned to caller.
- 6. Get locked Handle to DITL to be appended.
- 7. Calculate count of new items.
- */
-
- if (dialog == NULL) ExitToShell();
-
- max_rect = ((DialogPeek)dialog)->window.port.portRect;
- offset.v = max_rect.bottom;
- offset.h = 0;
- max_rect.bottom -= 5;
- max_rect.right -= 5;
-
- dlg_item_list = (ItemListHandle)((DialogPeek)dialog)->items;
- first_item = (**dlg_item_list).max_index + 2;
-
- append_item_list = (ItemListHandle)GetResource('DITL', item_list_ID);
- if ( append_item_list == NULL )
- return first_item;
-
- HLock((Handle)append_item_list);
- new_items = (**append_item_list).max_index + 1;
-
- /*
- For each item,
- 1. Offset the rectangle to follow the original window.
- 2. Make the original window larger if necessary.
- 3. fill in item handle according to type.
- */
-
- item = (**append_item_list).items;
- for ( i = 0; i < new_items; i++ )
- {
- OffsetRect(&item->bounds, offset.h, offset.v);
- UnionRect(&item->bounds, &max_rect, &max_rect);
- usb.integer = 0;
- usb.bytes[1] = item->data[0];
-
- switch ( item->type & 0x7F )
- {
- case ctrlItem + btnCtrl :
- case ctrlItem + chkCtrl :
- case ctrlItem + radCtrl :
- item->handle = (Handle)NewControl((DialogPtr) dialog,
- &item->bounds,
- (StringPtr)item->data,
- TRUE,
- 0, 0, 1,
- item->type & 0x03,
- 0);
- break;
-
- case ctrlItem + resCtrl :
- {
- item->handle = (Handle)GetNewControl(*(short*)(item->data + 1), (DialogPtr) dialog);
- (**(ControlHandle)item->handle).contrlRect = item->bounds;
- }
- break;
-
- case statText :
- case editText :
- err = PtrToHand(item->data + 1, &item->handle, usb.integer);
- break;
-
- case iconItem :
- item->handle = GetIcon(*(short*)(item->data + 1));
- break;
-
- case picItem :
- item->handle = (Handle)GetPicture(*(short*)(item->data + 1));
- break;
-
- default :
- item->handle = NULL;
- }
-
- data_size = (usb.integer + 1) & 0xFFFE;
- item = (DialogItemPtr)((char*)item + data_size + sizeof(DialogItem));
- }
-
- // We need to subtract the short below because otherwise the size of the DITL count
- // gets factored in twice, and the resulting DTIL has two bytes of garbage appended
- // to it. This is a problem with the original TN#95 code as well.
-
- err = PtrAndHand((**append_item_list).items,
- (Handle)dlg_item_list,
- GetHandleSize((Handle) append_item_list)
- - sizeof(short));
-
- (**dlg_item_list).max_index += new_items;
- HUnlock((Handle) append_item_list);
- ReleaseResource((Handle) append_item_list);
-
- max_rect.bottom += 5;
- max_rect.right += 5;
- SizeWindow((WindowPtr) dialog, max_rect.right, max_rect.bottom, TRUE);
-
- return first_item;
- }
-
-
- /*------------------------------------------------------------------------*/
-
- OSErr Print()
- {
- TPPrPort pPrPort;
- Rect aRect;
- TPrStatus theStatus;
-
-
- /* call PrJobInit to get pointer to the invisible job dialog */
- hPrintRec = (THPrint)(NewHandle(sizeof(TPrint)));
- PrintDefault(hPrintRec);
- PrValidate(hPrintRec);
- if (PrError() != noErr)
- return PrError();
-
- PrtJobDialog = PrJobInit(hPrintRec);
-
- if (PrError() != noErr)
- return PrError();
-
- if (!PrDlgMain(hPrintRec, NewPDlgInitProc(MyJobDlgInit))) /* this line does all the stuff */
- return iPrAbort;
-
- if (PrError() != noErr)
- return PrError();
-
- pPrPort = PrOpenDoc(hPrintRec, NULL, NULL);
- PrOpenPage(pPrPort, NULL);
-
- aRect = (*hPrintRec)->prInfo.rPage;
- InsetRect(&aRect, 20, 20);
- PenSize(4, 4);
- FrameRect(&aRect);
-
- PrClosePage(pPrPort);
- PrCloseDoc(pPrPort);
-
- if (!PrError() && (*hPrintRec)->prJob.bJDocLoop == bSpoolLoop)
- PrPicFile(hPrintRec, NULL, NULL, NULL, &theStatus);
-
-
- /* that's all for now */
-
- if (hPrintRec) DisposeHandle((Handle) hPrintRec);
-
- } /* Print */
-
- /*------------------------------------------------------------------------*/
-
- pascal TPPrDlg MyJobDlgInit (hPrint)
- THPrint hPrint;
- /*
- this routine appends items to the standard job dialog and sets up the
- user fields of the printing dialog record TPRDlg
-
- This routine will be called by PrDlgMain
- */
-
- {
- short firstItem; /* first new item number */
-
- short itemType, item;
- Handle itemH;
- Rect itemBox;
-
- firstItem = Append_DITL(PrtJobDialog, MyDITL); /*call routine to do this */
-
- prFirstItem = firstItem; /* save this so MyJobItems can find it */
-
- /* now we'll set up our DITL items -- The radio buttons */
-
- for (item = 5; item <= 7; item++)
- {
- GetDItem((DialogPtr) PrtJobDialog,firstItem + item -1,&itemType,&itemH,&itemBox);
- SetCtlValue((ControlHandle) itemH, (item == 5));
- }
-
- /* now we'll set up the second of our DITL items -- The checkbox */
-
- GetDItem((DialogPtr) PrtJobDialog,firstItem +2,&itemType,&itemH,&itemBox);
- SetCtlValue((ControlHandle) itemH,1);
-
- /*
- Now comes the part where we patch in our item handler. We have to save
- the old item handler address, so we can call it if one of the standard
- items is hit, and put our item handler's address in pItemProc field of
- the TPrDlg struct
- */
-
- prPItemProc = (long)PrtJobDialog->pItemProc;
-
- /* Now we'll tell the modal item handler where our routine is */
- PrtJobDialog->pItemProc = NewPItemProc(MyJobItems) ;
-
-
- /* PrDlgMain expects a pointer to the modified dialog to be returned...*/
- return PrtJobDialog;
-
- } /*myJobDlgInit*/
-
- /*-----------------------------------------------------------------------*/
-
- /* here's the analogue to the SF dialog hook */
-
- pascal void MyJobItems( TPPrDlg theDialog, short itemNo )
- { /* MyJobItems */
- short myItem;
- short firstItem, item, itemType, theValue;
- Handle itemH;
- Rect itemBox;
-
- firstItem = prFirstItem; /* remember, we saved this in myJobDlgInit */
- myItem = itemNo-firstItem+1; /* "localize" current item No */
- if (myItem > 0) /* if localized item > 0, it's one of ours */
- {
- /* find out which of our items was hit */
-
- switch (myItem)
- {
- case 1: /* Static text. */
- break;
- case 2: /* Edit text. */
- break;
- case 3: /* Check box. */
- GetDItem((DialogPtr) theDialog,firstItem +2,&itemType,&itemH,&itemBox);
- theValue = GetCtlValue((ControlHandle) itemH);
- SetCtlValue((ControlHandle) itemH, theValue != 1);
- break;
- case 4: /* Push button. */
- break;
- case 5: /* Radio buttons */
- case 6:
- case 7:
- for (item = 5; item <= 7; item++)
- {
- GetDItem((DialogPtr) theDialog,firstItem +item -1,&itemType,&itemH,&itemBox);
- SetCtlValue((ControlHandle) itemH, item == myItem);
- }
- break;
- case 8: /* Edit text. */
- break;
- default: Debugger(); /* OH OH */
- } /* switch */
- } /* if (myItem > 0) */
- else /* chain to standard item handler, whose address is saved in
- prPItemProc */
- {
-
- #if CFMSYSTEMCALLS
-
- // under ppc we need to create a proc info structure, this tells us
- // what the arguments are and how they get passed on the stack
- enum {
- uppPItemProcInfo = kPascalStackBased
- | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DialogPtr)))
- | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(short)))
- };
-
- // call the proc ptr we sut up in prPItemProc earlier
- CallUniversalProc((UniversalProcPtr) prPItemProc, uppPItemProcInfo, theDialog, itemNo) ;
-
- #else
-
- // for the 68k case use this. This code sucks, but it works...
- // call the standard item handler.
- ((pascal void (*) (TPPrDlg, short)) (Ptr) prPItemProc) (theDialog, itemNo);
-
- #endif
- }
- } /* MyJobItems */
-
-
- main()
- {
- Rect myWRect;
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- InitDialogs((long)nil);
- InitCursor();
- SetRect(&myWRect,50,260,350,340);
-
- /* call the routine that does printing */
- PrOpen();
- err = Print();
-
- PrClose();
- } /* main */
-